﻿using Microsoft.Xna.Framework;
using System;
using System.Diagnostics;
namespace Organized
{
    // A simple first person camera. Accepts rotation and translation
    public class ChaseCamera : Camera
    {
        //offset/positioning from camera target
        public Vector3 CameraPositionOffset = new Vector3(0, 70, -50);
        public Vector3 CameraTargetOffset = new Vector3(0, 20, 0);
        public float CameraTargetDistance = 280.0f;
        // higher values make camera follow slower
        public int cameraLazyness = 10;
        // Keeps track of the rotation and translation that have been
        // added via RotateTranslate()
        Vector3 rotation;
        Vector3 translation;

        HeightMapData heightMapInfo;

        //3d component to follow
        PhysicsVehicle target;

        Matrix smoothOrientation = Matrix.Identity;

        public ChaseCamera(GameScreen Parent) : base(Parent) {
            
        }

        public void addTarget(PhysicsVehicle _target){
            target = _target;
            CameraTargetDistanceZ = CameraPositionOffset.Z;
        }

        public void setHeightMapData(HeightMapData data)
        {
            heightMapInfo = data;
        }

        public override Vector3 Position
        {
            get { return position; }
            set { position = value; }
        }
        Vector3 position = Vector3.Zero;

        public bool VelocityFOV = false;

        float minimumHeight;
        Vector3 normal;
        Vector3 newPos;

        float CameraTargetDistanceZ;

        public override void Update()
        {
            if (VelocityFOV)
            {
                CameraPositionOffset.Z = -CameraTargetDistanceZ + ((FOV) * 130);
            }

          
            Matrix cameraFacingMatrix = Matrix.CreateRotationY(target.FacingDirection);
            Vector3 positionOffset = Vector3.Transform(CameraPositionOffset,
                cameraFacingMatrix);
            Vector3 targetOffset = Vector3.Transform(CameraTargetOffset,
                cameraFacingMatrix);

            //smooth positioning
            Position += ((target.Position + positionOffset) - Position) / cameraLazyness;
            

            // We don't want the camera to go beneath the heightmap (if there is one), so if the camera is
            // beneath the terrain, we'll move it up.
            if (heightMapInfo != null)
            {
                if (heightMapInfo.IsOnHeightmap(Position))
                {
                    // we don't want the camera to go beneath the terrain's height +
                    // a small offset.
                  
                    heightMapInfo.GetHeightAndNormal(Position, out minimumHeight, out normal);

                    minimumHeight += CameraPositionOffset.Y;
                    newPos = Position;
                    if (newPos.Y < minimumHeight)
                    {
                       
                        newPos.Y = minimumHeight;
                        Position = newPos;
                    }
                   
                }
            }

            // Update the rotation matrix using the rotation vector
            Rotation = MathUtil.Vector3ToMatrix(rotation);
            smoothOrientation.Up += (target.orientation.Up - smoothOrientation.Up) / 5;
            Up =smoothOrientation.Up;
            // Update the position in the direction of rotation
            translation = Vector3.Transform(translation, Rotation);

       
            Position += translation;

           
            // Reset translation
            translation = Vector3.Zero;

            // Calculate the new target
            Target = target.Position + targetOffset;

            View = Matrix.CreateLookAt(Position, Target, Up);

           
            float tFOV;
            //adjust cameras field of view
            /*
            if (target.movement.Z > 0)
            {
                tFOV = MathHelper.PiOver4 + MathHelper.ToRadians((target.ZSpeed/2) * (target.ZSpeed/2)) + 0.2f;
            }
            else
            {
                tFOV = MathHelper.PiOver4 + MathHelper.ToRadians((target.ZSpeed/2) * -(target.ZSpeed/2)) + 0.2f;
            }
             

            FOV += (tFOV - FOV) / 10;
             */
           
         

            Projection = MathUtil.CreateProjectionMatrix(FOV);
            
            //FrustumProjection = MathUtil.CreateProjectionMatrix(FOV, 2500.0f);
          
        }
    }
}